<template>
  <div class="my-table" :class="{'is-fit': fit}" v-loading="currentLoading" element-loading-spinner="el-icon-loading">
    <Toolbar v-if="toolbar" ref="toolbar" :title="title" :size="$attrs.size">
      <slot name="table-title" slot="title"></slot>
      <slot name="actions" slot="actions"></slot>
    </Toolbar>

    <el-table ref="elTable"
              :size="size"
              border
              :height="tableHeight"
              :data="list"
              v-bind="$attrs"
              v-on="$listeners">
      <el-table-column v-for="(col, index) in displayColumns"
                       :key="`${col.prop}_${col.type}_${index}`"
                       v-bind="col">
        <template v-if="col.type==='handle' || ( col.prop && $scopedSlots[col.prop])" v-slot="scope">
          <!-- 自定义字段 插槽-->
          <slot :name="col.prop || '_handle'" v-bind="scope" :column="col" ></slot>
        </template>

        <template v-if="col.type==='handle' || (col.prop && $scopedSlots[`${col.prop}.header`])"
                  v-slot:header="scope">
          <!-- 自定义字段表头 插槽-->
          <slot :name="`${col.prop||'_handle'}.header`" v-bind="{column:col, $index:index, ...scope}">
            {{col.label}}
          </slot>
        </template>
      </el-table-column>

      <el-table-column v-if="columnFilter" :resizable="false" align="center" width="24px" class-name="my-table--not-drag"
                   fixed="right">
        <ColumnFilter slot="header" :columns="columns" v-model="displayColumnProps"></ColumnFilter>
      </el-table-column>
    </el-table>

      <el-pagination ref="pager" class="pagination-container" v-if="pagination!==null && currentTotal"
                     v-bind="pagerProps"
                     :total="currentTotal"
                     :currentPage="currentPage"
                     @size-change="handlePageSizeChange"
                     @current-change="handlePageChange"
      >
      </el-pagination>
  </div>
</template>
<script>
import {getStyle} from 'element-ui/lib/utils/dom'
import ColumnFilter from './ColumnFilter'
import Toolbar from './Toolbar'

const defaultPagerProps = {
  background: true,
  layout: 'total, sizes, prev, pager, next, jumper'
}

export default {
  name: 'my-table',
  components: {
    ColumnFilter,
    Toolbar
  },
  props: {
    // 标题
    title: String,
    // 工具区
    toolbar: Boolean,
    size: {
      type: String,
      default: 'small'
    },
    // 加载数据函数
    loader: Function,
    // 实例化自动调用加载函数
    auto: {
      type: Boolean,
      default: true
    },
    // 列配置
    columns: Array,
    // 开启列筛选
    columnFilter: {
      type: Boolean,
      default: true
    },
    // 数组总数
    total: {
      type: Number,
      default: 0
    },
    // 初始页码
    page: {
      type: Number,
      default: 1
    },
    // 初始页大小
    pageSize: {
      type: Number,
      default: 10
    },
    // 分页组件其他配置
    pagination: {
      type: [Object, Boolean],
      default() {
        return {
          background: true,
          layout: 'total, sizes, prev, pager, next, jumper'
        }
      }
    },
    loading: Boolean,
    fit: Boolean,
    data: Array
  },
  data() {
    return {
      list: [],
      currentPage: this.page,
      currentTotal: this.total,
      currentPageSize: this.pageSize,
      currentLoading: this.loading,
      displayColumnProps: [],
      columnsProxy: [],
      toolbarHeight: 0,
      pagerHeight: 0
    }
  },
  methods: {
    resetDisplayColumns() {
      this.displayColumnProps = this.columnsProxy.filter(col => {
        if (!col.prop || col.type) return false
        return col.display !== false
      }).map(col => col.prop)
    },
    handlePageSizeChange(size) {
      this.currentPage = 1;
      this.currentPageSize = size
      /**
       * 页大小变化时触发
       * @event size-change
       * @param {number} pageSize 页大小
       */
      this.$emit('size-change', size)
      this.load()
    },
    handlePageChange(page) {
      this.currentPage = page
      /**
       * 分页页码变化时触发
       * @event page-change
       * @param {number} page 页码
       * @param {number} pageSize 页大小
       */
      this.$emit('page-change', page, this.currentPageSize)
      this.load()
    },
    load() {
      if (!this.loader) return
      this.currentLoading = true
      this.errorMessage = null

      this.loader(this.currentPage, this.currentPageSize).then(res => {
        this.list = res.list
        this.currentTotal = res.total || 0
        this.$emit('success', res)
      }).catch(e => {
        this.errorMessage = e;
        this.$emit('error', e)
      }).finally(() => {
        this.currentLoading = false
      })
    },
    refresh(page) {
      this.currentPage = page || this.currentPage
      this.load()
    },
    updateView() {
      if (this.$refs.toolbar) {
        const el = this.$refs.toolbar.$el
        const marginBottom = parseInt(getStyle(el, 'margin-bottom')) || 0
        this.toolbarHeight = el.getBoundingClientRect().height + marginBottom
      }
      if (this.$refs.pager) {
        const el = this.$refs.pager.$el
        const marginBottom = parseInt(getStyle(el, 'margin-bottom')) || 0
        const marginTop = parseInt(getStyle(el, 'margin-top')) || 0
        const pt = parseInt(getStyle(el, 'padding-top')) || 0
        const pb = parseInt(getStyle(el, 'padding-bottom')) || 0
        this.pagerHeight = el.getBoundingClientRect().height + marginBottom + marginTop + pt + pb
      }
    },
    getCurrentRow() {
      return this.$refs.elTable.store.states.currentRow
    }
  },
  watch: {
    columns: {
      immediate: true,
      handler() {
        this.columnsProxy = [...this.columns]
        this.resetDisplayColumns()
      }
    },
    list() {
      this.$nextTick(() => {
        this.updateView()
      })
    },
    data() {
      this.list = [].concat(this.data)
    }
  },
  computed: {
    displayColumns() {
      return this.columnsProxy.filter(col => {
        // 有type的字段 或 没设置属性名称的列固定显示
        if (col.type || !col.prop) return true
        return this.displayColumnProps.includes(col.prop)
      })
    },
    pagerProps() {
      return {
        ...defaultPagerProps,
        ...this.pagination,
        pageSize: this.pageSize,
        total: this.total,
        currentPage: this.page
      }
    },
    tableHeight() {
      if (!this.fit) return null
      return `calc(100% - ${this.toolbarHeight + this.pagerHeight}px)`
    }
  },
  mounted() {
    if(this.data) {
      this.list = [].concat(this.data)
    }
    this.updateView()
    if(this.auto) {
      this.load()
    }
  }
}
</script>
<style  lang="scss">
.my-table.is-fit {
  position: relative;
  height: 100%;
}
.my-table-column-filter__popper {
  max-width: 140px !important;
}
.pagination-container {
  position: relative;
  text-align: right;
}
</style>
